package com.naspan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.naspan.common.Result;
import com.naspan.common.config.AppConfig;
import com.naspan.common.constants.Constants;
import com.naspan.common.exception.bizExceptionHandle;
import com.naspan.entity.dto.RegisterDto;
import com.naspan.entity.dto.RegisterSendEmailCodeDto;
import com.naspan.entity.dto.SystemSetting;
import com.naspan.entity.dto.UserSpaceDto;
import com.naspan.entity.po.User;
import com.naspan.entity.vo.LoginUserVo;
import com.naspan.service.UserService;
import com.naspan.mapper.UserMapper;
import com.naspan.utils.RedisCache;
import com.naspan.utils.RedisCacheUtils;
import com.naspan.utils.ServletUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2023-09-30 14:09:16
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    public static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    public RedisCache redisCache = RedisCacheUtils.getRedisConfig();

    @Resource
    private JavaMailSender javaMailSender;

    @Resource
    private AppConfig appConfig;

    @Resource
    private UserMapper userMapper;

    @Override
    public void sendEmailCode(RegisterSendEmailCodeDto registerSendEmailCodeDto) {
        if (registerSendEmailCodeDto.getType() == 0) {
            User userInfo = this.getOne(new QueryWrapper<User>().lambda().eq(User::getUserId, registerSendEmailCodeDto.getEmail()));
            if (userInfo != null) {
                throw new bizExceptionHandle("邮箱已经存在");
            }
        }
        String code = RandomStringUtils.random(5, true, true);
        String toEmail = registerSendEmailCodeDto.getEmail();
        sendEmailCodeHandle(toEmail, code);
        redisCache.setCacheObject(Constants.Email_CODE + toEmail, code, Constants.Email_CODE_TTL, TimeUnit.MINUTES);
    }

    @Override
    public Result registerHandle(RegisterDto registerDto) {
        String toEmail = registerDto.getEmail();
        String redisKey = Constants.Email_CODE + toEmail;
        try {
            String emailCode = redisCache.getCacheObject(redisKey);
            if (StringUtils.isEmpty(emailCode)) {
                throw new bizExceptionHandle("邮箱验证码已过期");
            }
            if (!emailCode.equalsIgnoreCase(registerDto.getEmailCode())) {
                throw new bizExceptionHandle("邮箱验证码错误，请重新输入");
            }
            int count = this.count(new QueryWrapper<User>().lambda().eq(User::getNickName, registerDto.getNickName()));
            if (count > 0) {
                throw new bizExceptionHandle("昵称已存在");
            }
            User registerUser = new User();
            registerUser.setEmail(toEmail);
            registerUser.setNickName(registerDto.getNickName());
            registerUser.setPassword(DigestUtils.md5Hex(registerDto.getPassword()));
            registerUser.setUseSpace(0L);
            registerUser.setTotalSpace(new SystemSetting().getRegisterSpace() * 1024L * 1024L);
            registerUser.setStatus(1);
            this.save(registerUser);
            return Result.success("注册成功");
        } finally {
            redisCache.deleteObject(redisKey);
        }
    }

    @Override
    public void resetPassword(String email, String code, String password) {
        User userInfo = this.getOne(new QueryWrapper<User>().lambda().eq(User::getEmail, email));
        if (userInfo == null) {
            throw new bizExceptionHandle("邮箱不存在");
        }
        String redisKey = Constants.Email_CODE + email;
        try {
            String emailCode = redisCache.getCacheObject(redisKey);
            if (StringUtils.isEmpty(emailCode)) {
                throw new bizExceptionHandle("邮箱验证码已过期");
            }
            if (!emailCode.equalsIgnoreCase(code)) {
                throw new bizExceptionHandle("邮箱验证码错误，请重新输入");
            }
            userInfo.setPassword(DigestUtils.md5Hex(password));
            this.update(userInfo, new UpdateWrapper<User>().lambda().eq(User::getEmail, email));
        } finally {
            redisCache.deleteObject(redisKey);
        }
    }

    @Override
    public Result getUseSpace() {
        String userId = ServletUtils.getUser().getUserId();
        String key = Constants.USER_SPACE + userId;
        UserSpaceDto userSpaceDto = redisCache.getCacheObject(key);
        if (userSpaceDto==null) {
            userSpaceDto = new UserSpaceDto();
            userSpaceDto.setUseSpace(userMapper.getUseSpace(userId));
            userSpaceDto.setTotalSpace(this.getById(userId).getTotalSpace());
        }
        return Result.success(userSpaceDto);
    }

    @Override
    public LoginUserVo loginHandle(String email, String password, String code) {
        User user = this.getOne(new QueryWrapper<User>().lambda().eq(User::getEmail, email));
        if (user == null || !user.getPassword().equals(DigestUtils.md5Hex(password))) {
            throw new bizExceptionHandle("账号或密码错误");
        }
        if (user.getStatus() == 0) {
            throw new bizExceptionHandle("账号已被禁用");
        }
        user.setLastLoginTime(new Date());
        LoginUserVo loginUserVo = new LoginUserVo();
        BeanUtils.copyProperties(user, loginUserVo);
        loginUserVo.setIsAdmin(appConfig.getAdminEmail().equals(email));
        UserSpaceDto userSpaceDto = new UserSpaceDto();
        Long useSpace = userMapper.getUseSpace(user.getUserId());
        userSpaceDto.setUseSpace(useSpace);
        userSpaceDto.setTotalSpace(user.getTotalSpace());
        redisCache.setCacheObject(Constants.USER_SPACE + user.getUserId(), userSpaceDto);
        return loginUserVo;
    }

    private void sendEmailCodeHandle(String toEmail, String code) {
        try {
            SystemSetting systemSetting = new SystemSetting();
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
            mimeMessageHelper.setFrom(appConfig.getEmailForm());
            mimeMessageHelper.setTo(toEmail);
            mimeMessageHelper.setSentDate(new Date());
            mimeMessageHelper.setSubject(systemSetting.getRegisterMailTitle());
            mimeMessageHelper.setText(String.format(systemSetting.getRegisterMailContent(), code));
            javaMailSender.send(message);
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
    }
}




